/*************************************************

  Author:	
  Version:	1.01
  Date:
   Description:   
  Others:
  History:
    1. Date:
       Author:
       Modification:
    2. ...
*************************************************/
#include "..\user_config\includes.h"


#ifdef DEBUG_LCD
    FilterPara g_FilPara;
    FilterPara g_FilParaTab = {80,10,2,2,3,12,0,100,100,100};
#else
    FilterPara g_FilPara = {80,10,2,2,3,12,0,100,100,100};
#endif

#include <stdio.h>
#include <string.h>

#define xdata  
#define bit    BOOL    //--

#define AD_LIST_SIZE	(20)	
#define STABLE_CNT      (6)

static UINT_t  xdata g_Mini = 100;	// 081030 

INT16U SetDeltaScale12(UnitInfo * Unit1, CalInfo * pCal)
{
    INT16U uDelta;
    
    if (pCal->SPAN[0]==0 ||pCal->calWei==0||Unit1->div==0)
    {
        uDelta = 100;
    }
    else
    {
        uDelta =pCal->SPAN[0] / (pCal->calWei/Unit1->div);
    }
    return uDelta;
}
void SetDelata(INT8U uScale)
{
    if(uScale==SUB_SCALE)
        g_Mini = g_FilPara.nES2;
    else
        g_Mini = g_FilPara.nES1;        
}

// function:	insert the new AD value into the list
// value:		new AD value
// return:		start address of the list
static unsigned char volatile s_index = 0;
static unsigned long *InsertADValue(unsigned long value)
{
	static unsigned long xdata s_ADValueList[AD_LIST_SIZE] = { 0, };

	s_ADValueList[s_index] = value;
    s_index++;
	if(s_index>=AD_LIST_SIZE)
		s_index -= AD_LIST_SIZE;
	

	return s_ADValueList;
}

// function:	partition array A[0..uN-1] into two part.
//				A[0..PivotIndex-1] are no bigger than pivot value and
//				A[PivotIndex+1..uN-1] are no smaller than pivot value.
//				A[uN/2] is the pivot.
// A:			start address of array A
// uN:			element number of array A
// return:		index of pivot
static unsigned char partition(unsigned long *A, unsigned char uN)
{
	unsigned long *p, *q;
	unsigned long xdata pivot;

//	assert(A);
//	assert(uN>0);

	if(uN==1) return 0;

	p = A;
	q = A+uN-1;
	pivot = A[uN>>1];
	A[uN>>1] = A[0];

	while(p<q)
	{
		while(p<q&&*q>=pivot) --q;
		if(p<q) *p++ = *q;
		while(p<q&&*p<=pivot) ++p;
		if(p<q) *q-- = *p;
	}

	*p = pivot;

	return (unsigned char)(p-A);
}

// function:	find the Kth element of array A
// A:			start address of array A
// uN:			element number of array A
// K:			ordinal number (counted from 0)
// return:		value of the Kth element
static unsigned long FindKMedian(unsigned long *A, unsigned char uN, unsigned char K)
{
	unsigned long xdata pivot;
	unsigned char index;

	//assert(A);
	//assert(uN>0);
	//assert(K<uN);

	while(1)
	{
		index = partition(A, uN);
		pivot = A[index];
		if(index==K)
		{
			return pivot;
		}
		else if(index>K)
		{
			while(index>K&&A[index]==pivot)
				--index;

			if(A[index]==pivot)
			{
				return pivot;
			}
			else
			{
				uN = index + 1;
			}
		}
		else // index<K
		{
			while(index<K&&A[index]==pivot)
				++index;

			if(A[index]==pivot)
			{
				return pivot;
			}
			else
			{
				A += index;
				uN -= index;
				K -= index;
			}
		}
	}
}

static unsigned long FindNext(unsigned long *A)
{
	return A[(s_index==0)?(AD_LIST_SIZE-1):(s_index-1)];
}

// function:	get filtered value from array A
// A:			start address of array A
// uN:			element number of array A
// delta:		filter range. small - high quake proof level, large - low quake proof level
// return:		filtered value
static unsigned long GetFilteredValue(const unsigned long *A, unsigned char uN, bit bStable)
{
	unsigned long xdata tempArray[AD_LIST_SIZE];
	unsigned long xdata median;
    unsigned long xdata ulSum = 0;
	unsigned long volatile xdata		FilterResult=0;
	unsigned int volatile i;
    unsigned int count = 0;

	memcpy(tempArray, A, uN*sizeof(*A));
    
	if(bStable==TRUE)									// 081030 
		median = FindKMedian(tempArray, uN, (uN>>1));
    else    
		median = FindNext(tempArray);

    
               
    count=0;
	for(i=0; i<uN; i++)
	{
		if((median<=A[i]+10*g_Mini)&&(A[i]<=median+10*g_Mini))	
		{
			count++;
			ulSum += A[i];
		}
	}
	FilterResult = (ulSum)/count;


	return FilterResult;

}

// function:		get the filtered AD result
// global input
//	value_a:		AD value readed out by Read_ADIC()
//	d_quake:		quake proof level, 65535=low, 2=high
// global output
//	value_u:		filtered AD result
INT32U Filter(INT32U adData,FilterPara * pFilPara)
{
	static unsigned long xdata OldFilteredValue = 0;
	static unsigned long xdata s_filterResultTemp = 0;
    static INT16U uStaCnt = 0,uCnt;
    static INT32U aDataTmp[7];
   // static double dTmp = 0;
    unsigned long *ADValueList;
    BOOL bSta = 0;
	
    
	uCnt++;
	ADValueList = InsertADValue(adData);

    //--
    if(adData<s_filterResultTemp+10*g_Mini+Para[pFILTER]*10
        && s_filterResultTemp<adData+10*g_Mini+Para[pFILTER]*10)
    {       
        uStaCnt++;
        uStaCnt = uStaCnt>100?100:uStaCnt;
            
    }
    else
    {        
        uStaCnt = 0;
    }


    if(uStaCnt>AD_LIST_SIZE/2+8)
        bSta = TRUE;
    else
        bSta = FALSE;

        
  

    //aDataTmp[0] = GetFilteredValue(ADValueList, AD_LIST_SIZE,bSta);
    //dTmp = (double)(aDataTmp[0])*0.8+dTmp*0.2;
    //s_filterResultTemp = (INT32U)dTmp;
    s_filterResultTemp = GetFilteredValue(ADValueList, AD_LIST_SIZE,bSta);
    

    if(s_filterResultTemp<=(aDataTmp[6]+g_Mini/3*2)
        && s_filterResultTemp>=(aDataTmp[6]-g_Mini/3*2)
        &&uStaCnt>AD_LIST_SIZE/2+8)
    {
        pFilPara->bStable = TRUE;
    }
    else
    {
        pFilPara->bStable = FALSE;
    }
	
	if(uCnt%3==0)
	{
		aDataTmp[6] = aDataTmp[5];
		aDataTmp[5] = aDataTmp[4];
		aDataTmp[4] = aDataTmp[3];
		aDataTmp[3] = aDataTmp[2];
		aDataTmp[2] = aDataTmp[1];
		aDataTmp[1] = aDataTmp[0];
		aDataTmp[0] = s_filterResultTemp;
	}
    if((s_filterResultTemp<=(OldFilteredValue+g_Mini/4))
	 &&(s_filterResultTemp>=(OldFilteredValue-g_Mini/4))&&uStaCnt>AD_LIST_SIZE+10) 
	{
		s_filterResultTemp=OldFilteredValue;
	}
	else
	{
		OldFilteredValue= s_filterResultTemp;
        //uStaCnt = 0;
	}
        
    return s_filterResultTemp;
}



